/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.parameter_constraints;

import org.jmock.core.Constraint;

import picounit.DoubleParameterConstraints;
import picounit.features.constraint_store.ConstraintStore;

public class JMockDoubleConstraints implements DoubleParameterConstraints {
	private final ConstraintStore constraintStore;
	private final BasicParameterConstraints basicParameterConstraints;

	public JMockDoubleConstraints(ConstraintStore constraintStore) {
		this(constraintStore, new BasicParameterConstraints());
	}
	
	public JMockDoubleConstraints(ConstraintStore constraintStore, BasicParameterConstraints basicParameterConstraints) {
		this.constraintStore = constraintStore;
		this.basicParameterConstraints = basicParameterConstraints;
	}

	public double aDouble() {
		return constraintStore.putDouble(basicParameterConstraints.isAnything());
	}
	
	public double oneOf(double ... oneOf) {
		return constraintStore.putDouble(isEqual(oneOf));
	}
	
	public double neitherOf(double ... neitherOf) {
		return constraintStore.putDouble(basicParameterConstraints.not(isEqual(neitherOf)));
	}
	
	public double notEqualTo(double notEqual) {
		return constraintStore.putDouble(basicParameterConstraints.or(
			basicParameterConstraints.isLessThan(new Double(notEqual)),
			basicParameterConstraints.isGreaterThan(new Double(notEqual))));
	}
	
	public double lessThan(double upperLimit) {
		return constraintStore.putDouble(basicParameterConstraints.isLessThan(new Double(upperLimit)));
	}
	
	public double lessThanOrEqualTo(double upperLimit) {
		return constraintStore.putDouble(basicParameterConstraints.isLessThanOrEqualTo(new Double(upperLimit)));
	}
	
	public double greaterThan(double lowerLimit) {
		return constraintStore.putDouble(basicParameterConstraints.isGreaterThan(new Double(lowerLimit)));
	}
	
	public double greaterThanOrEqualTo(double lowerLimit) {
		return constraintStore.putDouble(basicParameterConstraints.isGreaterThanOrEqualTo(new Double(lowerLimit)));
	}
	
	public double between(double lowerLimit, double upperLimit) {
		return constraintStore.putDouble(basicParameterConstraints.isBetween(new Double(lowerLimit), new Double(upperLimit)));
	}
	
	public double notBetween(double lowerLimit, double upperLimit) {
		return constraintStore.putDouble(basicParameterConstraints.isNotBetween(new Double(lowerLimit), new Double(upperLimit)));
	}
	
	public double almostEqualTo(double equalTo, double errorAllowed) {
		errorAllowed = Math.abs(errorAllowed);
		
		return between(equalTo - errorAllowed, equalTo + errorAllowed);
	}
	
	private Constraint isEqual(double[] oneOf) {
		Constraint[] equals = new Constraint[oneOf.length];

		for (int index = 0; index < oneOf.length; index++ ) {
			equals[index] = basicParameterConstraints.isEqualTo(new Double(oneOf[index]));
		}

		return new ExtendedOr(equals);
	}
}
